<?php
/* 
Plugin Name: WP AJAX Edit Comments
Plugin URI: http://www.raproject.com/wordpress/wp-ajax-edit-comments/
Version: v1.1.4
Author: Ronald Huereca
Description: Allows you and your users to edit their comments inline.  Admin and editors can edit all comments.
Special Thanks: An extra special thanks goes out to Vivien from Inspiration Bit (http://www.inspirationbit.com).  Without her, this plugin release wouldn't have been possible.  Brett Terpstra from Circle Six Design (http://blog.circlesixdesign.com) helped fix a rather major bug as well during testing.  Thank you Brett.
 
Copyright 2007  Ronald Huereca  (email : ron alfy [a t ] g m ail DOT com)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

	class WPrapAjaxEditComments {
				var $commentClassName = "editComment"; //Do not edit this name
				var $commentAuthorName = "editAuthor"; //Do not edit this name
				var $skipDiv = false;
				var $minutes = 15;
				var $admin = "true";
				var $cookieName = "WPrapAjaxEditCommentId";//Do not edit this name
				var $optionsName = "WPAjaxEditComments"; //Do not edit this name
				var $userOptionsName = "WPAjaxEditAuthorUserOptions";
				var $adminOptions = false;
				var $userOptions = false; //Do not edit this name
				var $session = false;
				//constructor
				function WPrapAjaxEditComments() {
				}
				//Run when the plugin is first activated
				function init() {
					$this->getAdminOptions();
				}
				//Returns an array of admin options
				function getAdminOptions() {
					if ($this->adminOptions == false) {
						$optionsName = $this->optionsName;
						$adminOptions = array(
							'allow_editing' => 'true',
							'minutes' => '15', 
							'edit_text' => 'You may click on your name and/or comment to edit.', 
							'show_timer' => 'true',
							'spam_text' => 'Your edited comment was marked as spam.  If this is in error, please contact the admin.',
							'email_edits' => 'false',
							'number_edits' => '0',
							'use_akismet' => 'true',
							'use_mb_convert' => 'true'
						);
						$options = get_option($optionsName);
						if (!empty($options)) {
							foreach ($options as $key => $option)
								$adminOptions[$key] = $option;
						}				
						update_option($optionsName, $adminOptions);
						$this->adminOptions = $adminOptions;
					}
					return $this->adminOptions;
				}
				//Returns an array of user options
				function getUserOptions() {
					global $user_email;
					if ($this->userOptions == false) { 
						if (empty($user_email)) {get_currentuserinfo();}
						if (empty($user_email)) { return ''; }
						$optionsName = $this->userOptionsName;
						$defaults = array('author_editing' => 'true',
						'comment_editing' => 'true', 
						'admin_editing' => 'false',
						'inline_editing' => 'false',
						'show_links' => 'false'
						);
						$userOptions = get_option($optionsName);
						if (!isset($userOptions)) {
							$userOptions = array();
						}
						//See if an older version doesn't match the new defaults
						if (empty($userOptions[$user_email])) {
							$userOptions[$user_email] = $defaults;
							update_option(optionsName, $userOptions);
						}	elseif(!is_array($userOptions[$user_email])) {
							$userOptions[$user_email] = $defaults;
							update_option(optionsName, $userOptions);
						} else {
								foreach ($userOptions[$user_email] as $key => $option) {
									$defaults[$key] = $option;								
								}
								$userOptions[$user_email] = $defaults;
								update_option(optionsName, $userOptions);
						}
						$this->userOptions = $userOptions;
					}
					return $this->userOptions;
				}
				//Adds a paragraph to the beginning of the text
				//Takes in the text, a comment ID, and a post ID
				//Called by saveComment and addCommentDiv
				function addEditParagraph($text, $id, $postId) {
					if (empty($id)||empty($postId)) { return $text; }
					if (!$this->canEditPostsPage($postId)) {
							$text = "<p class='ajax-edit' id='ajax-edit" . $id . "'></p>" . $text;
							return $text;
					}
					return $text;
				}
				//Add in place holders for the Edit, Delete, Spam, Disapprove buttons - Skip out if in the admin panel
				function addApprovalParagraph($text, $commentId, $postId) {
					if ((empty($commentId) || empty($postId) || is_admin()) && $_GET['page'] != 'akismet-admin') { return $text; }
					global $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if (empty($user_email)) { return $text; }
					$author_options = $this->getUserOptions();
					//Get the author options
					if (!empty($author_options[$user_email])) {
						if ($author_options[$user_email]['show_links'] == "true") { return $text; }
					}
					$links = ''; 
					if ($this->canEditPostsPage() && $_GET['page'] != 'akismet-admin') {
						$links .= '<span><a class="ajax-admin-edit-links" href="#" id="edit' . $commentId . '">';
						$links .= __('Edit', "WPAjaxEditComments");
						$links .= '</a></span> | <span><a class="ajax-admin-edit-links" href="#" id="delete' . $commentId . '">';
						$links .= __('Delete',"WPAjaxEditComments" );
						$links .= '</a></span> | <span><a class="ajax-admin-edit-links" href="#" id="spam' . $commentId . '">';
						$links .= __('Spam',"WPAjaxEditComments" );
						$links .= '</a></span>';
					} elseif($this->canEditPostsPage() && $_GET['page'] == 'akismet-admin') {
						$links .= '<span><a class="ajax-akismet-links" href="#" id="unspam' . $commentId . '">';
						$links .= __('Not Spam', "WPAjaxEditComments" );
						$links .= '</a></span>';
					}
					if (strlen($links) > 0) 
						$text = $text . '<p style="display: none;" class="ajax-admin-edit-paragraph">[ ' . $links . ' ]</p>';
					
					return $text;
				}
				//Increments the number of edits users have made (excluding admin) - Takes in a post ID
				function incrementEdits($postId) {
					if (empty($postId)) { return; }
					$options = $this->getAdminOptions();
					$numEdits = intval($options['number_edits']);
					if (!$this->canEditPostsPage($postId)) {
						$numEdits += 1;
						$options['number_edits'] = $numEdits;
						update_option($this->optionsName, $options);
					}
				}
				//Returns true or false depending if the admin can inline edit
				function canInlineEdit() {
					global $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if (empty($user_email)) { return "true"; } //not logged in so they don't have a choice
					$author_options = $this->getUserOptions();
					//Get the author options
					if (!empty($author_options[$user_email])) {
						if ($author_options[$user_email]['inline_editing'] == "true") { return "false"; }
					}
					return "true";
				}
				//Adds a div to the comment text with a class name so that the AJAX can change the text to a textbox
				function addCommentDiv($text) { 
					global $comment;
					$className = "post";
					if (is_admin()) { $className = "admin"; }
					if (empty($comment)) { return $text; }
					if (!$this->canEdit($comment->comment_ID, $comment->comment_post_ID) || !$this->canEditComment()) { return $text; }
					
					//Skip this if admin
					$text = $this->addEditParagraph($text, $comment->comment_ID, $comment->comment_post_ID);
					
					if ($this->skipDiv) { return $text; }
					//Regular expression to check if there is a div already added
					$pattern = '/div class=\"' . $this->commentClassName . '\"/i';
					//If there is not a div already, add it in
					if (!preg_match($pattern, $text)) {
						$text = '<div class="'.$this->commentClassName. ' ' . $className.'" id="' . $this->commentClassName . $comment->comment_ID . '">' . $text .  '</div>';
					}
					$text = $this->addApprovalParagraph($text, $comment->comment_ID, $comment->comment_post_ID); 
					return $text;
				} //End function addCommentDiv()
				
				function addAuthorSpan($text) { 
					global $comment;
					$className = "post";
					if (is_admin()) { $className = "admin"; }
					if (!$this->canEdit($comment->comment_ID, $comment->comment_post_ID) || !$this->canEditAuthor()) { return $text; }
					//Regular expression to check if there is a div already added
					$pattern = '/span class=\"' . $this->commentAuthorName . '\"/i';
					
					//If there is not a div already, add it in
					if (!preg_match($pattern, $text)) {
						$text = '<span id="' . $this->commentAuthorName . $comment->comment_ID . '" class="' . $this->commentAuthorName . ' ' . $className .'">' . $text . '</span>';
					} 
					return $text;
				} //End function addAuthorDiv()
				
				//Prints out the admin page
				function printAdminPage() {
					global $wpdb;
					$WPAjaxEditComments = $this->getAdminOptions();
					if (!empty($savedOptions)) {
						$WPAjaxEditComments = $savedOptions;
					}
					if ( function_exists('current_user_can') && !current_user_can('manage_options') )
						 		die("nope");
					//Delete security keys 
					if (isset($_POST['update_wp_ajaxEditSecurityKeys'])) {
						check_admin_referer('wp-ajax-edit-comments_admin-options-security');
						$query = "delete from $wpdb->postmeta where left(meta_value, 6) = 'wpAjax'";
						if (@!$wpdb->query($query)) {
						?>
							<div class="error"><p><strong><?php _e('Security keys could not be deleted.', "WPAjaxEditComments") ?></strong></p></div>
						<?php
						} else {
							?>
							<div class="updated"><p><strong><?php _e('Security keys deleted', "WPAjaxEditComments") ?></strong></p></div>
						<?php
						}
					}
					//Update settings
					if (isset($_POST['update_wp_ajaxEditCommentSettings'])) { 
						 check_admin_referer('wp-ajax-edit-comments_admin-options');
						$error = false;
						$updated = false;
					  //Validate the comment time entered
						if (isset($_POST['wpAJAXCommentTime'])) {
							$commentTimeErrorMessage = '';
							$commentClass = 'error';
							if (!preg_match('/^\d+$/i', $_POST['wpAJAXCommentTime'])) {
								$commentTimeErrorMessage = "Comment time must be a numerical value";
								$error = true;
							}	elseif($_POST['wpAJAXCommentTime'] < 1) {
								$commentTimeErrorMessage = "Comment time must be greater than one minute.";
								$error = true;
							} else {
								$WPAjaxEditComments['minutes'] = $_POST['wpAJAXCommentTime'];
								$updated = true;
							}
							if (!empty($commentTimeErrorMessage)) {
							?>
<div class="<?php _e($commentClass, "WPAjaxEditComments");?>"><p><strong><?php _e($commentTimeErrorMessage, "WPAjaxEditComments");?></p></strong></div>
							<?php
							}
						}
						if (isset($_POST['wpAJAXCommentAllowEdit'])) {
							$WPAjaxEditComments['allow_editing'] = $_POST['wpAJAXCommentAllowEdit'];
							$WPAjaxEditComments['edit_text'] = apply_filters('title_save_pre',$_POST['wpAJAXEditText']);
							$WPAjaxEditComments['spam_text'] = apply_filters('pre_comment_content',apply_filters('comment_save_pre', $_POST['wpAJAXSpamText']));
							$WPAjaxEditComments['show_timer'] = $_POST['wpAJAXShowTimer'];
							$WPAjaxEditComments['email_edits'] = $_POST['wpAJAXEmailEdits'];
							$WPAjaxEditComments['use_akismet'] = $_POST['wpAJAXAkismet'];
							$WPAjaxEditComments['use_mb_convert'] = $_POST['wpAJAXmbConvert'];
							$update = true;
						}
						if ($updated && !$error) {
							update_option($this->optionsName, $WPAjaxEditComments);
							$this->adminOptions = $WPAjaxEditComments;
						?>
<div class="updated"><p><strong><?php _e('Settings successfully updated.', "WPAjaxEditComments") ?></strong></p></div>
					<?php
						}
					} ?>
<div class="wrap">
<form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
<?php wp_nonce_field('wp-ajax-edit-comments_admin-options') ?>
<h2><?php _e("WP AJAX Edit Comment", 'WPAjaxEditComments') ?></h2>
<p><?php _e("Your commentators have edited their comments ", 'WPAjaxEditComments') ?><?php _e(number_format(intval($WPAjaxEditComments['number_edits'])),"WPAjaxEditComments") ?> <?php _e("times.", "WPAjaxEditComments") ?></p>
<p><label for="comment_time"><?php _e('Set comment time (minutes):', "WPAjaxEditComments") ?> </label><input type="text" name="wpAJAXCommentTime" value="<?php echo $WPAjaxEditComments['minutes'] ?>" id="comment_time"/></p>
<p><label for="edit_text"><?php _e('Set edit text (no HTML allowed):', "WPAjaxEditComments") ?> </label><br/><input size="75" type="text" name="wpAJAXEditText" value="<?php _e(format_to_edit(stripslashes($WPAjaxEditComments['edit_text'])), 'WPAjaxEditComments')  ?>" id="edit_text"/></p>
<p><label for="spam_text"><?php _e('Set spam notification text.  Please limit to one line if possible since this text will show up when editing the comment or author (Tags allowed: em, a, strong, blockquote):', "WPAjaxEditComments") ?> </label><br/><textarea cols="100" rows="3" name="wpAJAXSpamText" id="spam_text"><?php _e(stripslashes(apply_filters('comment_edit_save', $WPAjaxEditComments['spam_text'])), "WPAjaxEditComments")?></textarea></p>
<h3><?php _e('Allow Anyone to Edit Their Own Comments?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "No" will turn off comment editing for everyone except admin types who have post and page editing permissions.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXCommentAllowEdit_yes"><input type="radio" id="wpAJAXCommentAllowEdit_yes" name="wpAJAXCommentAllowEdit" value="true" <?php if ($WPAjaxEditComments['allow_editing'] == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes','WPAjaxEditComments'); ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXCommentAllowEdit_no"><input type="radio" id="wpAJAXCommentAllowEdit_no" name="wpAJAXCommentAllowEdit" value="false" <?php if ($WPAjaxEditComments['allow_editing'] == "false") { echo('checked="checked"'); }?>/> <?php _e('No','WPAjaxEditComments'); ?></label></p>
<h3><?php _e('Show a Countdown Timer?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "No" will turn off the countdown timer for non-admin commentators.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXShowTimer_yes"><input type="radio" id="wpAJAXShowTimer_yes" name="wpAJAXShowTimer" value="true" <?php if ($WPAjaxEditComments['show_timer'] == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes','WPAjaxEditComments'); ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXShowTimer_no"><input type="radio" id="wpAJAXShowTimer_no" name="wpAJAXShowTimer" value="false" <?php if ($WPAjaxEditComments['show_timer'] == "false") { echo('checked="checked"'); }?>/> <?php _e('No','WPAjaxEditComments'); ?></label></p>
<h3><?php _e('Allow Edit E-mails?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will send you an email each time someone edits their comment.  This is not recommended for high-traffic blogs.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXEmailEdits_yes"><input type="radio" id="wpAJAXEmailEdits_yes" name="wpAJAXEmailEdits" value="true" <?php if ($WPAjaxEditComments['email_edits'] == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes','WPAjaxEditComments'); ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXEmailEdits_no"><input type="radio" id="wpAJAXEmailEdits_no" name="wpAJAXEmailEdits" value="false" <?php if ($WPAjaxEditComments['email_edits'] == "false") { echo('checked="checked"'); }?>/> <?php _e('No','WPAjaxEditComments'); ?></label></p>
<h3><?php _e('Check Edited Comments Against Akismet (if installed)?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will submit the comment to Akismet for re-validation after every edit.  This is strongly recommended since users can write a benign comment, but add in spam links after an edit.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXAkismet_yes"><input type="radio" id="wpAJAXAkismet_yes" name="wpAJAXAkismet" value="true" <?php if ($WPAjaxEditComments['use_akismet'] == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes','WPAjaxEditComments'); ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXAkismet_no"><input type="radio" id="wpAJAXAkismet_no" name="wpAJAXAkismet" value="false" <?php if ($WPAjaxEditComments['use_akismet'] == "false") { echo('checked="checked"'); }?>/> <?php _e('No','WPAjaxEditComments'); ?></label></p>
<h3><?php _e('Disable mb_convert_encoding?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Some servers do not have this installed.  If you disable this option, be sure to test out various characters.  The mb_convert_encoding function is necessary to convert from UTF-8 to various charsets.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXmbConvert_yes"><input type="radio" id="wpAJAXmbConvert_yes" name="wpAJAXmbConvert" value="true" <?php if ($WPAjaxEditComments['use_mb_convert'] == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes','WPAjaxEditComments'); ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXmbConvert_no"><input type="radio" id="wpAJAXmbConvert_no" name="wpAJAXmbConvert" value="false" <?php if ($WPAjaxEditComments['use_mb_convert'] == "false") { echo('checked="checked"'); }?>/> <?php _e('No','WPAjaxEditComments'); ?></label></p>
<div class="submit">
<input type="submit" name="update_wp_ajaxEditCommentSettings" value="<?php _e('Update Settings', 'WPAjaxEditComments') ?>" /></div>
</form>
 </div>
 <div class="wrap">
<form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
<?php wp_nonce_field('wp-ajax-edit-comments_admin-options-security') ?>
<h3><?php _e("Delete all security keys (ensure you have a recent backup)?", "WPAjaxEditComments") ?></h3>
<p><?php _e("Each time a user leaves a comment, a security key is stored as a custom key.  Periodically you may want to delete this information.  Please backup your database first.", "WPAjaxEditComments") ?></p>
<p><?php _e("For versions earlier than 1.1.0.4, you will have to log into phpMyAdmin and run this query (please back up your database first):  <strong>delete from wp_postmeta where length(meta_value) = 96</strong>", "WPAjaxEditComments") ?></p>
<div class="submit">
<input type="submit" name="update_wp_ajaxEditSecurityKeys" value="<?php _e('Delete security keys', 'WPAjaxEditComments') ?>" /></div>
</form>
 </div>
					<?php
				}//End function printAdminPage()
				
				//Prints out the author page
				function printAuthorPage() {
					global $wpdb, $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if ( function_exists('current_user_can') && !current_user_can('manage_options') )
						 		die("nope");
					$author_options = $this->getUserOptions();
					//Save the updated options to the database
					if (isset($_POST['wpAJAXAuthor']) && isset($_POST['wpAJAXComment']) && isset($_POST['wpAJAXAdminEdits'])&& isset($_POST['wpAJAXInlineEdits'])&& isset($_POST['wpAJAXLinks'])) {
					check_admin_referer('wp-ajax-edit-comments_user-options');
						if (isset($user_email)) {
							$author_options[$user_email]['author_editing'] = $_POST['wpAJAXAuthor'];
							$author_options[$user_email]['comment_editing'] = $_POST['wpAJAXComment'];
							$author_options[$user_email]['admin_editing'] = $_POST['wpAJAXAdminEdits'];
							$author_options[$user_email]['inline_editing'] = $_POST['wpAJAXInlineEdits'];
							$author_options[$user_email]['show_links'] = $_POST['wpAJAXLinks'];
							?>
								<div class="updated"><p><strong>Settings successfully updated.</strong></p></div>
							<?php
							update_option($this->userOptionsName, $author_options);
							$this->userOptions = $author_options;
						}
					}
					//Get the author options
					if (!empty($author_options[$user_email])) {
							$author = $author_options[$user_email]['author_editing'];
							$comment = $author_options[$user_email]['comment_editing'];
							$adminEdits = $author_options[$user_email]['admin_editing'];
							$inlineEdits = $author_options[$user_email]['inline_editing'];
							$showLinks = $author_options[$user_email]['show_links'];
						}
					?>
<div class=wrap>
<form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
<?php wp_nonce_field('wp-ajax-edit-comments_user-options') ?>
<h2><?php _e('WP AJAX Edit Comment - Individual User Options', "WPAjaxEditComments") ?></h2>
<h3><?php _e('Turn Off Comment Editing in Admin Panel?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will disable comment editing in the Admin Comments Panel. This option is irrelevant if Name Editing and Comment Editing are disabled (see below).', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXAdminEdits_yes"><input type="radio" id="wpAJAXAdminEdits_yes" name="wpAJAXAdminEdits" value="true" <?php if ($adminEdits == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes', "WPAjaxEditComments") ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXAdminEdits_no"><input type="radio" id="wpAJAXAdminEdits_no" name="wpAJAXAdminEdits" value="false" <?php if ($adminEdits == "false") { echo('checked="checked"'); }?>/> <?php _e('No', "WPAjaxEditComments") ?></label></p>
<h3><?php _e('Turn Off Inline Editing?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will disable the "edit in place" type comment editing in a post.  The admin panel is unaffected by this option.  This option is irrelevant if Name Editing and Comment Editing are disabled (see below).', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXInlineEdits_yes"><input type="radio" id="wpAJAXInlineEdits_yes" name="wpAJAXInlineEdits" value="true" <?php if ($inlineEdits == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes', "WPAjaxEditComments") ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXInlineEdits_no"><input type="radio" id="wpAJAXInlineEdits_no" name="wpAJAXInlineEdits" value="false" <?php if ($inlineEdits == "false") { echo('checked="checked"'); }?>/> <?php _e('No', "WPAjaxEditComments") ?></label></p>
<h3><?php _e('Turn Off Comment Post Links?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will disable the links that show up underneath a comment.  These links allow you to edit, delete, or mark a comment as spam.  These links are also disabled if you disable comment editing (see below).', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXLinks_yes"><input type="radio" id="wpAJAXLinks_yes" name="wpAJAXLinks" value="true" <?php if ($showLinks == "true") { echo('checked="checked"'); }?> /><?php _e(' Yes', "WPAjaxEditComments") ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXLinks_no"><input type="radio" id="wpAJAXLinks_no" name="wpAJAXLinks" value="false" <?php if ($showLinks == "false") { echo('checked="checked"'); }?>/> <?php _e('No', "WPAjaxEditComments") ?></label></p>
<h3><?php _e('Turn On Name Editing?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will enable your ability to edit the author details.  Selecting "No" will disable your ability to edit comment author details in the post and admin panel.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXAuthor_yes"><input type="radio" id="wpAJAXAuthor_yes" name="wpAJAXAuthor" value="true" <?php if ($author == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes', "WPAjaxEditComments") ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXAuthor_no"><input type="radio" id="wpAJAXAuthor_no" name="wpAJAXAuthor" value="false" <?php if ($author == "false") { echo('checked="checked"'); }?>/> <?php _e('No', "WPAjaxEditComments") ?></label></p>
<h3><?php _e('Turn On Comment Editing?', "WPAjaxEditComments") ?></h3>
<p><?php _e('Selecting "Yes" will enable your ability to edit a user\'s comment.  Selecting "No" will disable your ability to edit comments in the post and admin panel.', "WPAjaxEditComments") ?></p>
<p><label for="wpAJAXComment_yes"><input type="radio" id="wpAJAXComment_yes" name="wpAJAXComment" value="true" <?php if ($comment == "true") { echo('checked="checked"'); }?> /> <?php _e('Yes', "WPAjaxEditComments") ?></label>&nbsp;&nbsp;&nbsp;&nbsp;<label for="wpAJAXComment_no"><input type="radio" id="wpAJAXComment_no" name="wpAJAXComment" value="false" <?php if ($comment == "false") { echo('checked="checked"'); }?>/> <?php _e('No', "WPAjaxEditComments") ?></label></p>

<div class="submit">
<input type="submit" name="update_wp_ajaxEditCommentSettings" value="<?php _e('Update Settings', 'WPAjaxEditComments') ?>" /></div>
</form>
 </div>
					<?php
				}//End function printAuthorPage()
				
				//Adds the appropriate JavaScript files into the head tag
				function addHeaderJS() {
					global $post;
					if (empty($post)) { return; }
					//Load the appropriate files only if the page is single -- Wouldn't want to hit on a non-single post. :)
					if (is_single() || is_page()) {
						$this->JS();
					}
				}//End function addHeaderJS
				
				function addAdminHeaderJS() {
				   //Page detection for other plugin authors
				   if ('index.php' != basename($_SERVER['SCRIPT_FILENAME']) && 'edit-comments.php' != basename($_SERVER['SCRIPT_FILENAME']) && 'moderation.php' != basename($_SERVER['SCRIPT_FILENAME']))
				      return;
				   
					global $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if (empty($user_email)) { return; }
					$author_options = $this->getUserOptions();
					//Get the author options
					if (!empty($author_options[$user_email])) {
						if ($author_options[$user_email]['admin_editing'] == "true") { return; }
					}
					$this->JS();
				}
				function JS() {
					if (function_exists('wp_enqueue_script') && function_exists('wp_register_script')) {
						wp_register_script('jquery', get_bloginfo('wpurl') . '/wp-content/plugins/wp-ajax-edit-comments/js-includes/jquery.js');
						wp_enqueue_script('ajax_edit_comments', get_bloginfo('wpurl') . '/wp-content/plugins/wp-ajax-edit-comments/js-includes/wp-ajax-edit-comments.js.php', array('jquery'), '1.1');
					}
				}
				function CSS() {
					echo "<link type=\"text/css\" rel=\"stylesheet\" href=\"" . get_bloginfo('wpurl') . "/wp-content/plugins/wp-ajax-edit-comments/css/editComments.css\" />\n";
				}
				//Returns a comment for editing in a textbox
				//Takes in a comment id
				function getComment($id) {
					global $wpdb;
					$comment = get_comment( $id );
					if (!$comment) { return 0; }
					if (!$this->canEditPostsPage($comment->comment_post_ID)) { if ($comment->comment_approved === "spam") { return false; } }
					if (!$this->canEdit($id, $comment->comment_post_ID)) { return false; }	
					//Get the comment ready for the textbox
					$content = $comment->comment_content;
					$content = apply_filters('comment_edit_save', $content);
					return $content;
				}//End function getComment
				//Strips the ID to just numbers
				function convert_smart_quotes($string) { //Necessary for reading in comments - from http://shiflett.org/blog/2005/oct/convert-smart-quotes-with-php
						$search = array(chr(145), chr(146), chr(147),	chr(148), chr(151)); 
				 		$replace = array("'","'",'"','"','-');				 
						return str_replace($search, $replace, $string); 
				} 
				function getCommentID($id) {
					preg_match('/([0-9]+)$/i', $id, $matches);
					if (is_numeric($matches[1])) {
						return $matches[1];
					} else { 
						return 0;
					}
				} //End function getCommentID
				//Returns the text such as "You may click on author/comment to edit"
				function getEditText() {
					$options = $this->getAdminOptions();
					return  attribute_escape($options['edit_text']);	
				}
				//Returns the spam text such as "Your comment has been flagged as spam.  Please contact admin..."
				function getSpamText() {
					$options = $this->getAdminOptions();
					$content = $options['spam_text'];
					
					$this->skipDiv = true;
					$content = apply_filters('comment_text', $content);
					$this->skipDiv = false;
					
					return stripslashes($content);					
				}
				
				function deleteComment($id) {
					if (empty($id)) { return false; }
					if ($this->canEditPostsPage()) {
						if (!wp_delete_comment($id)) { return false; }
						return true;
					} 
					return false;
				}
				//Spams or De-spams a comment
				//$id = the comment id - $action ("0"=de-spam, "1"=spam).
				function spamComment($id, $action) {
					if (empty($id)) { return false; }
					if ( $this->canEditPostsPage() ) { 
						if ($action == "1" ) { if (!wp_set_comment_status($id, 'spam')) { return false; } }
						if ($action == "0" ) { if (!wp_set_comment_status($id, 'approve')) { return false; } }
						return true;
					}
					return false;
				}
				//Returns how much time is left to edit on a comment in a comma deliminated variable 
				//Returns $minutes,$seconds
				//Takes in a comment ID
				//One concern here is if the admin increases the time in the admin panel - The user will be under the impression that there is more time to edit than there really is.  This is a minor and rare bug, so I chose to leave it alone.
				function getTimeLeft($id) {
					global $wpdb;
					if (empty($id)) { return "0,0"; }
					$adminEdit = $this->getAdminOptions();
					$adminMinutes = $adminEdit['minutes'];
						$query = "SELECT (UNIX_TIMESTAMP('" . current_time('mysql') . "') - UNIX_TIMESTAMP(comment_date)) time FROM $wpdb->comments where comment_ID = $id";
					//Get the IP, Date, and Timestamp
					$comment = $wpdb->get_row($query, ARRAY_A);
					//Get the time elapsed since making the comment
					$time = $comment['time'];
					$timeLeft = ($adminMinutes * 60) - $time; //seconds
					if ($timeLeft <= 0) { return "0,0"; }
					$minutesPassed = floor($timeLeft/60);
					$seconds = $timeLeft - ($minutesPassed*60);
				return "$minutesPassed,$seconds";		
				}//end function getTimeLeft
				
				//Saves the author to the database
				/*id = The comment id
				url = The author's url
				name = The author's name*/
				function saveAuthor($id, $url, $name) {
					global $wpdb;
					if (strtolower(get_option('blog_charset')) != 'utf-8') { $wpdb->query("SET names 'utf8'");} //comment out if getting char errors
					$comment = get_comment($id, ARRAY_A);
					if (!$comment) { return 0; }
					if (!$this->canEditPostsPage($comment['comment_post_ID'])) { if ($comment['comment_approved'] === "spam") { return 0; } }
					if (!$this->canEdit($id, $comment['comment_post_ID'])) { return 0; }
					if (!isset($name)) {
						return 0;
					}
					if (trim($name) == '') { return 0; }
					$url = urldecode($url);
					$name = urldecode($name);
					$url = trim(apply_filters('comment_url', $url));
					$saveUrl = apply_filters('pre_comment_author_url', $url);
					$name = apply_filters('comment_author', $name);
					$saveName = apply_filters('pre_commment_author_name', $name);
					
					if(!$wpdb->query("UPDATE $wpdb->comments SET comment_author = '$saveName', comment_author_url = '{$saveUrl}' WHERE comment_ID = $id")) {
						return 0;
					}
					//For WP Cache
					if (function_exists("wp_cache_get_postid_from_comment")) {
						wp_cache_get_postid_from_comment($id);
					}
					//Check for spam
					if ($this->checkSpam($id, $comment['comment_post_ID'])) { return "spam"; }
					//Send out edit notifications
					$this->editNotification($id, $comment['comment_post_ID']);
					$this->incrementEdits($comment['comment_post_ID']);

					$url = stripslashes($this->encode($url));
					$name = stripslashes($this->encode($name));
					$returnText = '';
					if (!empty($url)) {
						$returnText = '<a href="' . $url . '">' . $name . '</a>';
					} else {
						$returnText = $name;
					}
					return $returnText;
				
				} //End function saveAuthor
				//Saves the edited comment to the database
				function saveComment($id, $content) {
						global $wpdb; //ISO-8859-1
					if (strtolower(get_option('blog_charset')) != 'utf-8') { $wpdb->query("SET names 'utf8'");} //comment out if getting char errors
					$comment = get_comment($id, ARRAY_A);
					$content = urldecode($content);
					$savecontent = $content;
										
					if (trim($content) == '' || !$comment ) { return 0; }
					if (!$this->canEditPostsPage($comment['comment_post_ID'])) { if ($comment['comment_approved'] === "spam") { return 0; } }
					if (!$this->canEdit($id, $comment['comment_post_ID'])) { return 0; }
					$content = apply_filters('comment_save_pre', $savecontent);
					if(!$wpdb->query("UPDATE $wpdb->comments SET comment_content = '$content' WHERE comment_ID = $id")) {	
						return 0;
					}
					if (function_exists('clean_comment_cache')) { clean_comment_cache($id); } //Clear cache for comment
					//For WP Cache
					if (function_exists("wp_cache_get_postid_from_comment")) {
						wp_cache_get_postid_from_comment($id);
					}
					//Check for spam
					if ($this->checkSpam($id, $comment['comment_post_ID'])) { return "spam" ;}
					//Send out edit notifications
					$this->editNotification($id, $comment['comment_post_ID']);
					$this->incrementEdits($comment['comment_post_ID']);
					$this->skipDiv = true;
					$content = apply_filters('comment_text', $this->encode($content));
					$content = $this->addEditParagraph($content, $id, $comment['comment_post_ID']);
					$this->skipDiv = false;
					return stripslashes($content);
				} //end function saveComment
				function encode($content) {
				   $adminEncode = $this->getAdminOptions();
				   if ($adminEncode['use_mb_convert'] == "false" || !function_exists("mb_convert_encoding")) { return $content; }
				   return mb_convert_encoding($content, ''.get_option('blog_charset').'', mb_detect_encoding($content, "UTF-8, ISO-8859-1, ISO-8859-15", true));
				}
				//Return true if spam, return false if not (or if ID is invalid or Akismet isn't installed)
				function checkSpam($id, $postId) {
					if (empty($id) || empty($postId)) { return false; }
					$options = $this->getAdminOptions();
					if ($options['use_akismet'] == "false") { return false;} //Check to see if the admin has enabled akismet checking
					//Check for SPAM if Akismet is installed
					if (function_exists("akismet_check_db_comment")) {
						if (!$this->canEditPostsPage()) { //Skip if admin
							if (akismet_verify_key(get_option('wordpress_api_key')) != "failed") { //If API key fails, keep on going as if Akismet isn't installed
								$response = akismet_check_db_comment($id);
								if ($response == "true") { //You have spam
									wp_set_comment_status($id, 'spam');
									return true;
								}
							}
						}
					}
					return false;			
				}
				//Sends a notification of an edit via e-mail - Code sampled from Subscribe to Comments
				//Takes in a comment ID and Post ID - Returns false if email failed
				function editNotification($id, $postId) {
					global $wpdb;
					
					if (empty($id) || empty($postId)) { return false; }
					//Make sure this option is enabled and the user editing isn't admin
					$options = $this->getAdminOptions();
					if ($options['email_edits'] == "false" || $this->canEditPostsPage()) { return false; }
					
					$comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID='$id' LIMIT 1", ARRAY_A);
					$post = $wpdb->get_row("SELECT * FROM $wpdb->posts WHERE ID='$comment->comment_post_ID' LIMIT 1", ARRAY_A);
					if ( $comment['comment_approved'] == '1' && $comment['comment_type'] == '' ) { // Comment has been approved and isn't a trackback or a pingback, so we should send out notifications
						$message  = sprintf(__("A comment has been edited on post %s", 'WPAjaxEditComments') . ": \n%s\n\n", stripslashes($post['post_title']), get_permalink($comment['comment_post_ID']));
						$message .= sprintf(__("Author: %s\n", 'WPAjaxEditComments'), $comment['comment_author']);
						$message .= sprintf(__("Author URL: %s\n", 'WPAjaxEditComments'), stripslashes($comment['comment_author_url']));
						$message .= __("Comment:\n", 'WPAjaxEditComments') . stripslashes($comment['comment_content']) . "\n\n";
						$message .= __("See all comments on this post here:\n", 'WPAjaxEditComments');
						$message .= get_permalink($comment['comment_post_ID']) . "#comments\n\n";
						$subject = sprintf(__('New Edited Comment On: %s', 'WPAjaxEditCommentss'), stripslashes($post['post_title']));
						$subject = '[' . get_bloginfo('name') . '] ' . $subject;
						$email = get_bloginfo('admin_email');
						$site_name = str_replace('"', "'", get_bloginfo('name'));
						$charset = get_settings('blog_charset');
						$headers  = "From: \"{$site_name}\" <{$email}>\n";
						$headers .= "MIME-Version: 1.0\n";
						$headers .= "Content-Type: text/plain; charset=\"{$charset}\"\n";
						return wp_mail($email, $subject, $message, $headers);
					}
					return false;
				}
				//Determines if a comment can be edited or not based on the ID and time elapsed
				//$id = The comment id
				//$postId = The post id for the comment
				//Returns true if the comment can be edited, false if not
				function canEdit($id, $postId) {
					global $wpdb;
					if (empty($id) || empty($postId)) { return false; }
					//Return true if the user can edit the comment
					if ($this->canEditPostsPage()) { return true; }
					
					//Checks to see if the admin has allowed comment editing
					$adminEdit = $this->getAdminOptions();
					$adminEdit = $adminEdit['allow_editing'];
					if ($adminEdit != 'true') {
						return false;
					}
					$query = "SELECT UNIX_TIMESTAMP(comment_date) time, comment_author_IP, comment_date_gmt, comment_post_ID, comment_ID  FROM $wpdb->comments where comment_ID = $id";
					//Get the IP, Date, and Timestamp
					$comment = $wpdb->get_row($query, ARRAY_A); if (!comment) { return false; }
					$meta = $wpdb->get_row("SELECT meta_value FROM $wpdb->postmeta WHERE post_id = " . $comment['comment_post_ID'] . " and meta_key = " . $comment['comment_ID'], ARRAY_A);
					if (!meta || !$comment) { return false; }
					$timestamp = $comment['time'];
					$hash = md5($comment['comment_author_IP'] . $comment['comment_date_gmt']);
					//Check to see if there's a valid cookie
					if (!$this->session) { @session_start(); $this->session = true; }
					if (isset($_COOKIE[$this->cookieName . $id . $hash]) || isset($_SESSION[$this->cookieName . $id . $hash])) {
						if (!($_COOKIE[$this->cookieName . $id . $hash] === $meta['meta_value']) && !($_SESSION[$this->cookieName . $id . $hash] === $meta['meta_value'])) { return false; }
						//Get the time elapsed since making the comment
						$time = current_time('timestamp',get_option('gmt_offset'))-$timestamp;
						$minutesPassed = round(((($time%604800)%86400)%3600)/60); 
						//Get the time the admin has set for minutes
						$minutes = $this->getAdminOptions();
						$minutes = $minutes['minutes'];
						if (!is_numeric($minutes)) {
							$minutes = $this->minutes;
						}
						if ($minutes < 1) {
							$minutes = $this->minutes;
						}
						//Compare the minutes passed to the admin minutes
						if (($minutesPassed - $minutes) > 0) {
							unset($_SESSION[$this->cookieName . $id . $hash]); return false; 
						}
						return true;
					}
					@session_write_close();
					return false;
				}//end function canEdit
				
				//Returns true if a person can edit a post/page - User level 9 and above
				//Returns false otherwise
				//Called by canEdit() and setCommentCookie
				function canEditPostsPage() {
					global $userdata;
					get_currentuserinfo();
					if (empty($userdata->user_level)) { return false; }
					if ($userdata->user_level >= '9') { return true; } else { return false; }
				}//end function canEditPostsPage
				
				//Returns true unless the user has disabled author editing
				function canEditAuthor() {
					global $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if (empty($user_email)) { return true; }
					$author_options = $this->getUserOptions();
					//Get the author options
					if (!empty($author_options[$user_email])) {
						if ($author_options[$user_email]['author_editing'] == "false") { return false; }
					}
					return true;
				} //end function canEditAuthor
				
				//Returns true unless the user has disabled comment editing
				function canEditComment() { 
					global $user_email;
					if (empty($user_email)) {
						get_currentuserinfo();
					}
					if (empty($user_email)) { return true; }
					$author_options = $this->getUserOptions();
					//Get the author options
					if (!empty($author_options[$user_email])) {
						if ($author_options[$user_email]['comment_editing'] == "false") { return false; }
					}
					return true;
				
				}
				
				//Sets a comment cookie for the commentator (treat as a private function)
				function setCommentCookie($commentId) {
					global $comment, $wpdb;
					//Get the IP, Date, and Timestamp
					if (empty($comment)) {
						$comment = $wpdb->get_row("SELECT * FROM $wpdb->comments where comment_ID = $commentId", ARRAY_A);
					}
					if (!$comment) { return $commentId; }
					if ($comment['comment_approved'] === "spam") { return $commentId; }
					
					//Return if setting the cookie is unnecessary
					if ($this->canEditPostsPage()) { return $commentId; }
					
					$hash = md5($comment['comment_author_IP'] . $comment['comment_date_gmt']);
					$rand = 'wpAjax' . $hash . md5($this->random()) . md5($this->random());
					//Get the time the admin has set for minutes
					$minutes = $this->getAdminOptions();
					$minutes = $minutes['minutes'];
					if (!is_numeric($minutes)) {
						$minutes = $this->minutes;
					}
					if ($minutes < 1) {
						$minutes = $this->minutes;
					}		
					
					//Insert the random key into the database
					$query = "INSERT INTO " . $wpdb->postmeta .
            "(meta_id, post_id, meta_key, meta_value) " .
            "VALUES ('', " . $comment['comment_post_ID'] . "," . $comment['comment_ID'] . ",'" . $rand . "')";
					@$wpdb->query($query);
						
					//Set the cookie
					$cookieName = $this->cookieName . $commentId . $hash;
					$value = $rand;
					$expire = time()+60*$minutes;
					if (!isset($_COOKIE[$cookieName])) {
						setcookie($cookieName, $value, $expire, COOKIEPATH,COOKIE_DOMAIN);
						session_start();
						$_SESSION[$cookieName] = $value;
						session_write_close();
					}
					return $commentId;
				} //end function setCommentCookie
				
				function random() {
				 $chars = "%CDEF#cGHIJ\:ab!@defg9ABhijklmn<>;opqrstuvwxyz10234/+_-=5678MKL^&*NOP";
				 $pass = '';
				 for ($i = 0; $i < 50; $i++) {
				 	$pass .= $chars{rand(0, strlen($chars)-1)};
				 }
				 return $pass;
				}
				//Returns a nonce - Takes in the nonce name - Returns a nonce in the format of _wpnonce:"404049"
				function getNonce($name) {
					$nonce = $this->nonceReplace(wp_nonce_url("#", $name));
					if ($this->canEditPostsPage()) { //yay, admin
						$nonce = '_wpnonce:"' . md5($nonce) . '"';
					} else { //yay, non-admin user
						$nonce = '_wpnonce:"' . md5(md5($nonce) . $nonce) . '"';
					}
					return $nonce;				
				}
				//takes in a wp_nonce and changes it from format  _wpnonce=404049# to 404049
				function nonceReplace($nonce) {
					$nonce = str_replace("_wpnonce=", '', $nonce);
					$nonce = str_replace("#", '', $nonce);
					return $nonce;
				}
				//Takes in the nonce with format 404049, and the nonce name
				//Return true if the nonce is valid, false if not
				function verifyNonce($nonce, $name) {
					$newNonce = $this->nonceReplace(wp_nonce_url("#", $name));
					//Figure out if we are admin or just a user
					if ($this->canEditPostsPage()) { //yay, admin
						$newNonce = md5($newNonce);
						if ($nonce != $newNonce) {
							return false;
						}
					} else { //yay, non-admin user
						$newNonce = md5(md5($newNonce) . $newNonce);
						if ($nonce != $newNonce) {
							return false;
						}
					}
				return true;
				} //end function verifyNonce
		}//End Class WPrapAjaxEditComments
if (class_exists("WPrapAjaxEditComments")) {
$rap_ajaxComment = new WPrapAjaxEditComments();

//locale stuff
$rap_ajaxComment_locale = get_locale();
$rap_ajaxComment_mofile = dirname(__FILE__) . "/languages/ajaxEdit-$rap_ajaxComment_locale.mo";
load_textdomain('WPAjaxEditComments', $rap_ajaxComment_mofile);
}
//Initialize the admin panel
function WPrapAjaxEditComments_ap() {
	global $rap_ajaxComment;
	if (!isset($rap_ajaxComment)) {
		return;
	}
	if (function_exists('add_options_page')) {
add_options_page('AJAX Edit Comments', 'AJAX Edit Comments', 10, basename(__FILE__), array(&$rap_ajaxComment, 'printAdminPage'));
	}
	if (function_exists('add_submenu_page')) {
		add_submenu_page('profile.php', "AJAX Edit Comments Options","AJAX Edit Comments", 9, basename(__FILE__), array(&$rap_ajaxComment, 'printAuthorPage'));
	}
}	
//Template tag WPrapAjaxEditComments_CanEdit 
//Returns true if a user can edit - False if they can't - Must be run within the loop
//Also returns false if people are admins
function WPrapAjaxEditComments_CanEdit() {
	global $comment, $rap_ajaxComment;
	//If we're not in the loop, return false
	if (!isset($comment) || !isset($rap_ajaxComment)) { return false; }
	
	//If admin, return false
	if ($rap_ajaxComment->canEditPostsPage()) {
		return false;
	}
	//Find out if the user can edit
	if ($rap_ajaxComment->canEdit($comment->comment_ID, $comment->comment_post_ID)) {
		return true;
	}
	return false;	
}
//Yay, actions.	
if (isset($rap_ajaxComment)) {
	add_action('admin_menu', 'WPrapAjaxEditComments_ap');
	add_action('admin_print_scripts', array(&$rap_ajaxComment, 'addAdminHeaderJS')); 
	add_action('admin_head', array(&$rap_ajaxComment, 'CSS')); 
	add_action('wp_print_scripts', array(&$rap_ajaxComment, 'addHeaderJS'));
	add_action('wp_head', array(&$rap_ajaxComment, 'CSS'));
	add_action('comment_post', array(&$rap_ajaxComment, 'setCommentCookie'));
	add_action('activate_wp-ajax-edit-comments/wp-ajax-edit-comments.php',  array(&$rap_ajaxComment, 'init'));
	
	//Yay, filters.
	add_filter('comment_text', array(&$rap_ajaxComment, 'addCommentDiv'), '1000'); //Low priority so other HTML can be added first
	add_filter('get_comment_author_link', array(&$rap_ajaxComment, 'addAuthorSpan'), '1000'); //Low priority so other HTML can be added first
}

?>